package com.cheng.student.service;

import com.cheng.student.beans.AmountAndListStu;
import com.cheng.student.beans.Student;
import com.cheng.student.beans.StudentFull;
import com.cheng.student.dao.InsertFailedException;
import com.cheng.student.dao.StudentDao;
import com.cheng.student.dao.mappers.StudentMapper;
import com.cheng.student.service.interfaces.StudentService;
import com.cheng.student.utils.GetJsonUtil;
import com.cheng.student.utils.SqlSessionGetter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.junit.jupiter.api.Test;


import java.io.*;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;

public class StudentServiceImpl
    implements StudentService
{

    @Override
    public List<StudentFull> getStudentsByExcel(InputStream excel,int numberOfRows)
    {
        long currentTimeMillis = System.currentTimeMillis();
        List<StudentFull> students = null;
        boolean isOnlyNumber = true;
        try
        {
            //获取一个excel对象
            Workbook workbook = WorkbookFactory.create(excel);

            //获取一个sheet对象
            Sheet sheet0 = workbook.getSheetAt(0);

            //为迭代创建计数器，方便寻找迭代到哪一列
            int rowTimer = 0;

            int cellTimer0 = 0;

            //存放StudentFull的list
            students = new LinkedList<>();

            //第一行（命名的行）
            Row row0 = sheet0.getRow(0);

            for (Row row: sheet0)
            {
                rowTimer++;
                if(rowTimer == 1)
                {
                    continue;
                }
                //超过了行数就退出
                else if(rowTimer == numberOfRows + 1)
                {
                    break;
                }

                //创建StudentFull对象储存表格的数据
                StudentFull studentFull = new StudentFull();

                //使用反射为对象的成员变量赋值
                Class<? extends StudentFull> aClass = studentFull.getClass();

                for(Cell cell: row0)
                {

                    cellTimer0++;

                    //单个学生的某一属性与属性值
                    String name = cell.toString();
                    String value = row.getCell(cellTimer0 - 1) != null ? row.getCell(cellTimer0 - 1).toString() : "";

                    //判断value是否为纯数字如果是则去小数点
                    int length = value.length();

                    for (int i = 0;i < length;i++)
                    {
                        char c = value.charAt(i);
                        //不是纯数字
                        if((c < 48 || c > 57) && c != 46)
                        {
                            isOnlyNumber = false;
                        }
                        //是纯数字
                        else { }
                    }
                    //去点儿
                    if (isOnlyNumber)
                    {
                        value = value.split("\\.")[0];
                    }
                    isOnlyNumber = true;
                    //学生成员变量的对象（反射）
                    Field field = null;
                    try
                    {
                        field = aClass.getDeclaredField(name);
                        field.setAccessible(true);
                        field.set(studentFull,value);
                    }
                    catch (NoSuchFieldException e)
                    {
                        e.printStackTrace();
                        System.out.println(name + "变量在类中不存在");
                    }
                    catch (IllegalAccessException e)
                    {
                        e.printStackTrace();
                        System.out.println(name + "值添加失败");
                    }
                }
                //初始化计数器并添加学生对象到集合中
                cellTimer0 = 0;
                students.add(studentFull);


            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }


        System.out.println(System.currentTimeMillis() - currentTimeMillis);
        return students;
    }

    @Override
    public Student studentLogin(String name, String number)
    {
        Student student = StudentDao.getStudent(name, number);
        return student;
    }

    @Override
    public StudentFull getStudentFull(String name, String number)
    {
        SqlSession sqlSession = SqlSessionGetter.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        StudentFull studentFull = mapper.selectStudentFull(name, number);

        sqlSession.close();
        return studentFull;
    }

    @Override
    public int getNumberOfStudent()
    {
        SqlSession sqlSession = SqlSessionGetter.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        int number = mapper.selectNumberOfStudents();
        sqlSession.close();
        return number;
    }


    public static void main(String[] args)
            throws IOException, InsertFailedException
    {

        StudentServiceImpl studentService = new StudentServiceImpl();
        File file = new File("C:\\Users\\31869\\IdeaProjects\\studentAdmissionSystem\\src\\main\\resources\\现教中心学生团队2021级最终考核：附件1.xlsx");

        FileInputStream fileInputStream = new FileInputStream(file);
        studentService.insertStudentsByExcel(fileInputStream,200);
    }

    @Override
    public void insertStudentsByExcel(InputStream inputStream, int numberOfRows)
            throws InsertFailedException
    {
        List<StudentFull> students = getStudentsByExcel(inputStream, numberOfRows);

        StudentDao.insertStudents(students);;

        return;
    }

    @Override
    public String getJsonOfStudentFulls(
            String area,
            String gender,
            String academy,
            String major,
            String batch,
            String type,
            int start,
            int end)
    {
        SqlSession sqlSession = SqlSessionGetter.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        List<StudentFull> studentFulls = mapper.selectStudentFulls(
                area, gender, academy, major, batch, type, start, end - start + 1);

        int amount = mapper.selectNumbers(area, gender, academy, major, batch, type);

        sqlSession.close();

        AmountAndListStu amountAndList = new AmountAndListStu(amount, studentFulls);

        String json = GetJsonUtil.getJson(amountAndList);

        return json;
    }

    @Override
    public String getSuchValuesJson(String key)
            throws JsonProcessingException
    {
        SqlSession sqlSession = SqlSessionGetter.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        List<String> values = mapper.selectValues(key);

        List<String> valuesNoDuplicated = new LinkedList<>();
        //去重
        boolean isDuplicated = false;
        for (String value: values)
        {
            isDuplicated = false;
            for (String value1: valuesNoDuplicated)
            {
                if (value1.equals(value))
                {
                    isDuplicated = true;
                }
            }
            if (!isDuplicated)
            {
                valuesNoDuplicated.add(value);
            }
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(valuesNoDuplicated);
        sqlSession.close();
        return json;
    }

    @Override
    public boolean updateStudentFull(String name, String number, String key, String value)
    {
        SqlSession sqlSession = SqlSessionGetter.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        if(0 == mapper.updateStudentByNameNumber(name, number, key, value))
        {
            return false;
        }

        sqlSession.close();

        return true;
    }

    @Override
    public int deleteStudent(String name, String number)
    {
        SqlSession sqlSession = SqlSessionGetter.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        int i = mapper.deleteStudent(name, number);

        sqlSession.close();
        return i;
    }
}
